package org.mbcorp.sar.model;

import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;

import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.springframework.web.multipart.MultipartFile;


@Entity
@Table
public class Solicitud implements Serializable{
	
	private static final long serialVersionUID = 1L;

	@Id
    @GeneratedValue(strategy = GenerationType.AUTO)
	private Integer id;
	
	@Column(nullable = false)
	private String desc1;
	
	@Column(nullable = false)
	private String desc2;
	
	@Column(nullable = false)
	private String desc3;
	
	@Column(nullable = false)
	private String desc4;
	
	@Column(nullable = false)
	private String desc5;
		
	@Column(nullable = false)
	private Date fechaRegistro;
	
	@Column(nullable = false)
	private String estado;	

	@Column(nullable = false)
	private boolean flagAprobado;
	
	@Column(nullable = false)
	private boolean flagBaja;
	
	@Column(nullable = false)
	private boolean flagVerificado;

	@Column(nullable = true)
	private String comentariosVerif;	
	
	@Column(nullable = true)
	private Date fechaverif;
	
	@Column(nullable = true)
	private Date fechaInicio;
	
	@Column(nullable = true)
	private Date fechaFin;
	
	@Column(nullable = false)
	private boolean flagSolucionAprobada;
	
	@JoinColumn(name = "solicitante", referencedColumnName = "Id")
	@ManyToOne(optional = false, fetch = FetchType.EAGER)
	private Solicitante solicitante;

	@Column(nullable = true)
	private Date fechaEsperada;
	
	@JoinColumn(name = "areaSolicitante", referencedColumnName = "id")
	@ManyToOne(optional = false, fetch = FetchType.EAGER)
	private Area areaSolicitante;
	
	@JoinColumn(name = "tipoRequerimiento", referencedColumnName = "id")
	@ManyToOne(optional = false, fetch = FetchType.EAGER)
	private TipoRequerimiento tipoRequerimiento;
	
	@JoinColumn(name = "archivo", referencedColumnName = "id")
	@ManyToOne(optional = true, fetch = FetchType.EAGER)
	private Archivo archivo;
	
	@Column(nullable = false)
	private boolean flagEstimado;
	
	@Column(nullable = false)
	private boolean flagReprogramar;
	
	@Column(name = "FlagProgramado", nullable = false)
	private boolean flagProgramado;
	
//	@OneToMany(fetch = FetchType.EAGER)
//	@JoinColumn(name = "Solicitud", nullable = true)
//	@IndexColumn(name= "OrdenFase")
	@OneToMany(mappedBy = "solicitud")
	@LazyCollection(LazyCollectionOption.FALSE)
	@OrderBy("ordenFase ASC")
	private List<Fase> fases;	
	
	@Column(name = "FechaProgramacion", nullable = false)
	private Date fechaProgramacion;
	
	@Column(name = "FlagFueraPlazoAprobacion", nullable = true)
	private boolean flagFueraPlazoAprobacion;
	
	@Column(name = "FechaAcordadaEntrega")
	private Date fechaAcordadaEntrega;
	
	@Column(name = "ComentariosReprogramacion", nullable = true)
	private String comentariosReprogramacion;
	
	// A partir de este punto los atributos no son parte de la entidad, sino para transporte de datos.
	
	@NotNull(groups=BusquedaValidate.class)
	@Transient
	private Date fechaBusquedaInicio;
	
	@NotNull(groups=BusquedaValidate.class)
	@Transient
	private Date fechaBusquedaFin;
	
	@Transient
	private boolean porNumero;
	
	//TODO retirar y cambiar por requestparam
	@Transient
	private boolean flagAdjuntar;
	
	@Transient
	private MultipartFile archivoAux;
	
	@Transient
	private String clienteBusqueda;
	
	@Transient
	private int totalHorasEstimadas;
	
	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}	
	
	public String getDesc1() {
		return desc1;
	}

	public void setDesc1(String desc1) {
		this.desc1 = desc1;
	}

	public String getDesc2() {
		return desc2;
	}

	public void setDesc2(String desc2) {
		this.desc2 = desc2;
	}

	public String getDesc3() {
		return desc3;
	}

	public void setDesc3(String desc3) {
		this.desc3 = desc3;
	}

	public String getDesc4() {
		return desc4;
	}

	public void setDesc4(String desc4) {
		this.desc4 = desc4;
	}

	public String getDesc5() {
		return desc5;
	}

	public void setDesc5(String desc5) {
		this.desc5 = desc5;
	}

	public TipoRequerimiento getTipoRequerimiento() {
		return tipoRequerimiento;
	}

	public void setTipoRequerimiento(TipoRequerimiento tipoRequerimiento) {
		this.tipoRequerimiento = tipoRequerimiento;
	}

	public Date getFechaRegistro() {
		return fechaRegistro;
	}

	public void setFechaRegistro(Date fechaRegistro) {
		this.fechaRegistro = fechaRegistro;
	}

	public String getEstado() {
		return estado;
	}

	public void setEstado(String estado) {
		this.estado = estado;
	}

	public boolean isFlagAprobado() {
		return flagAprobado;
	}

	public void setFlagAprobado(boolean flagAprobado) {
		this.flagAprobado = flagAprobado;
	}

	public boolean isFlagBaja() {
		return flagBaja;
	}

	public void setFlagBaja(boolean flagBaja) {
		this.flagBaja = flagBaja;
	}

	public boolean isFlagVerificado() {
		return flagVerificado;
	}

	public void setFlagVerificado(boolean flagVerificado) {
		this.flagVerificado = flagVerificado;
	}

	public String getComentariosVerif() {
		return comentariosVerif;
	}

	public void setComentariosVerif(String comentariosVerif) {
		this.comentariosVerif = comentariosVerif;
	}

	public Date getFechaverif() {
		return fechaverif;
	}

	public void setFechaverif(Date fechaverif) {
		this.fechaverif = fechaverif;
	}

	public Date getFechaInicio() {
		return fechaInicio;
	}

	public void setFechaInicio(Date fechaInicio) {
		this.fechaInicio = fechaInicio;
	}

	public Date getFechaFin() {
		return fechaFin;
	}

	public void setFechaFin(Date fechaFin) {
		this.fechaFin = fechaFin;
	}

	public boolean isFlagSolucionAprobada() {
		return flagSolucionAprobada;
	}

	public void setFlagSolucionAprobada(boolean flagSolucionAprobada) {
		this.flagSolucionAprobada = flagSolucionAprobada;
	}

	public Solicitante getSolicitante() {
		return solicitante;
	}

	public void setSolicitante(Solicitante solicitante) {
		this.solicitante = solicitante;
	}

	public Date getFechaEsperada() {
		return fechaEsperada;
	}

	public void setFechaEsperada(Date fechaEsperada) {
		this.fechaEsperada = fechaEsperada;
	}

	public Area getAreaSolicitante() {
		return areaSolicitante;
	}

	public void setAreaSolicitante(Area areaSolicitante) {
		this.areaSolicitante = areaSolicitante;
	}

	public Archivo getArchivo() {
		return archivo;
	}

	public void setArchivo(Archivo archivo) {
		this.archivo = archivo;
	}

	public boolean isFlagEstimado() {
		return flagEstimado;
	}

	public void setFlagEstimado(boolean flagEstimado) {
		this.flagEstimado = flagEstimado;
	}

	public boolean isFlagReprogramar() {
		return flagReprogramar;
	}

	public void setFlagReprogramar(boolean flagReprogramar) {
		this.flagReprogramar = flagReprogramar;
	}

	public List<Fase> getFases() {
		return fases;
	}

	public void setFases(List<Fase> fases) {
		this.fases = fases;
	}

	public boolean isFlagProgramado() {
		return flagProgramado;
	}

	public void setFlagProgramado(boolean flagProgramado) {
		this.flagProgramado = flagProgramado;
	}

	public Date getFechaBusquedaInicio() {
		return fechaBusquedaInicio;
	}

	public void setFechaBusquedaInicio(Date fechaBusquedaInicio) {
		this.fechaBusquedaInicio = fechaBusquedaInicio;
	}

	public Date getFechaBusquedaFin() {
		return fechaBusquedaFin;
	}

	public void setFechaBusquedaFin(Date fechaBusquedaFin) {
		this.fechaBusquedaFin = fechaBusquedaFin;
	}

	public boolean isPorNumero() {
		return porNumero;
	}

	public void setPorNumero(boolean porNumero) {
		this.porNumero = porNumero;
	}

	public boolean isFlagAdjuntar() {
		return flagAdjuntar;
	}

	public void setFlagAdjuntar(boolean flagAdjuntar) {
		this.flagAdjuntar = flagAdjuntar;
	}

	public MultipartFile getArchivoAux() {
		return archivoAux;
	}

	public void setArchivoAux(MultipartFile archivoAux) {
		this.archivoAux = archivoAux;
	}

	public String getClienteBusqueda() {
		return clienteBusqueda;
	}

	public void setClienteBusqueda(String clienteBusqueda) {
		this.clienteBusqueda = clienteBusqueda;
	}

	public Date getFechaProgramacion() {
		return fechaProgramacion;
	}

	public void setFechaProgramacion(Date fechaProgramacion) {
		this.fechaProgramacion = fechaProgramacion;
	}


	public int getTotalHorasEstimadas() {
		return totalHorasEstimadas;
	}
	

	public void setTotalHorasEstimadas(int totalHorasEstimadas) {
		this.totalHorasEstimadas = totalHorasEstimadas;
	}
	
	public Date getFechaAcordadaEntrega() {
		return fechaAcordadaEntrega;
	}

	public void setFechaAcordadaEntrega(Date fechaAcordadaEntrega) {
		this.fechaAcordadaEntrega = fechaAcordadaEntrega;
	}

	@Transient
	public Integer getHorasRestantesAprobacion(){
		if(this.getFechaProgramacion() != null){
			Calendar fechaActual = Calendar.getInstance();
			Calendar fechaPlazo = Calendar.getInstance();
			fechaPlazo.setTime(this.getFechaProgramacion());
			fechaPlazo.add(Calendar.DAY_OF_MONTH, this.getSolicitante().getCliente().getDiasPlazoAprobacion());
			return (int) ((fechaPlazo.getTimeInMillis() - fechaActual.getTimeInMillis())/ (60 * 60 * 1000));
		}
		return null;
	}	

	public boolean isFlagFueraPlazoAprobacion() {
		return flagFueraPlazoAprobacion;
	}

	public void setFlagFueraPlazoAprobacion(boolean flagFueraPlazoAprobacion) {
		this.flagFueraPlazoAprobacion = flagFueraPlazoAprobacion;
	}	
	
	public String getComentariosReprogramacion() {
		return comentariosReprogramacion;
	}

	public void setComentariosReprogramacion(String comentariosReprogramacion) {
		this.comentariosReprogramacion = comentariosReprogramacion;
	}

	@Transient
	public Date getFechaEstimadaEntrega() {
		if(this.getFases() != null){
			Date fechaEstimadaEntrega = this.getFases().get(0).getHorarios().get(0).getFechaFin();
			for(Fase f: this.getFases()){
				for(Horario h : f.getHorarios()){
					if(h.getFechaFin().after(fechaEstimadaEntrega)){
						fechaEstimadaEntrega = h.getFechaFin();
					}
				}
			}
			return fechaEstimadaEntrega;
		}
		return null;
	}

	@Transient
	public boolean isTieneFasesAbiertas(){
		if(this.getFases() != null){
			for(Fase fase : this.getFases()){
				if(fase.getFechaFin() == null){
					return true;
				}
			}
		}		
		return false;
	}

	public interface BusquedaValidate {
    }


	
}


	
